﻿#region copyright
//<copyright>
// Copyright(C) 2012 TrackerRealm Corporation
// This file is part of the open source project - Jazz. http://jazz.codeplex.com
// 
// Jazz is open software: you can redistribute it and/or modify it 
// under the terms of the GNU Affero General Public License (AGPL) as published by 
// the Free Software Foundation, version 3 of the License.
// 
// Jazz is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty 
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
//  See the GNU Affero General Public License (AGPL) for more details.
// 
// You should have received a copy of the GNU General Public 
// License along with Jazz.  If not, see <http://www.gnu.org/licenses/>.
//
// REMOVAL OF THIS NOTICE IS VIOLATION OF THE COPYRIGHT. 
//</copyright>
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;
using TrackerRealm.Jazz.Common;
using C = TrackerRealm.Jazz.Common.JazzConstants;

// namespace will change for this class
namespace TrackerRealm.Jazz.Client
{
    /// <summary>
    /// A workspace is simalar to a directory in a file system.
    /// A Workspace contains workflows including other workspaces.
    /// All Jazz Objects ('<see cref="jObject"/>') must belong to one and only one workspace.
    /// <para>For more information see http://wiki.jazzfire.net/workspace.ashx </para>
    /// </summary>
    [Root]
    [Jazz]
    public abstract class jWorkspaceBase : jNameUnique, IEnumerable<jObject>
    {
        #region Constructor
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="name"></param>
        protected jWorkspaceBase(string name)
        :base(name)
        {
            this._IsPartiallyCached = false;
        }
        #endregion
        #region Constructor
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="nexus"></param>
        /// <param name="name"></param>
        protected jWorkspaceBase(ClientNexusBase nexus, string name)
            : base(nexus, name)
        {
            this._IsPartiallyCached = false;
        }
        #endregion

        #region IsPartiallyCached
        /// <summary>
        /// 
        /// </summary>
        protected internal bool _IsPartiallyCached
        {
            get;
            set;
        }
        #endregion
        #region Move
        /// <summary>
        /// Moves this workspace to be a child of the specified 'jazzObject'.
        /// </summary>
        /// <param name="jazzObject"></param>
        protected void _Move(jObject jazzObject)
        {
            jazzObject.Workspace = this;
        }
        #endregion
        #region Add/Remove AclItem
        /// <summary>
        /// The ACL (Access Control List) controls how this '<see cref="jObject"/>' instance
        /// can be accessed.
        /// <para>Note: If the ACL sequence is empty then there are no access restrictions.</para>
        /// </summary>
        internal protected override IEnumerable<jAclItem> _ACL
        {
            get { return base._ACL; }
            set
            {
                jObject[] children = this.ToArray();
                base._ACL = value;
                children.Foreach(j => j.SetAccessibility(base.ClientNexus));
            }
        }
        #endregion
        #region IEnumerable<jObject> Members
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        [AccessorMethod]
        public virtual IEnumerator<jObject> GetEnumerator()
        {
            return this.ClientNexus.Cache.OfType<jObject>().Where(j => j.Workspace == this).GetEnumerator();
        }
        #endregion
        #region IEnumerable Members
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        [AccessorMethod]
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        #endregion

        #region ACL -Add/Remove
        
        /// <summary>
        /// Add a '<see cref="jAclItem"/>' to this jObject's ACL.
        /// </summary>
        /// <param name="item"></param>
        protected void _AddACL(jAclItem item)
        {
            if (this.IsWorkspacePublic()) throw new InvalidOperationException("The 'Public' workspace is not allowed to have an non-empty ACL.");
            base._Add(item);
        }
        /// <summary>
        /// Remove a '<see cref="jAclItem"/>' from this jObject's ACL.
        /// </summary>
        /// <param name="item"></param>
        protected void _RemoveACL(jAclItem item)
        {
            if (this.IsWorkspacePublic()) throw new InvalidOperationException("The 'Public' workspace is not allowed to have an non-empty ACL.");
            base._Remove(item);
        }
        #endregion
    }
}
